"""硬件监控核心"""

import asyncio
from typing import Dict, Any, List, Optional
from dataclasses import dataclass


@dataclass
class HardwareSensor:
    """硬件传感器数据"""
    name: str
    value: float
    unit: str
    min_value: Optional[float] = None
    max_value: Optional[float] = None
    critical_value: Optional[float] = None


@dataclass
class HardwareComponent:
    """硬件组件"""
    name: str
    component_type: str  # cpu, gpu, memory, storage, network
    sensors: List[HardwareSensor]


class HardwareMonitor:
    """硬件监控器"""
    
    def __init__(self):
        self.hardware_monitor = None
        self.fallback_monitor = None
        self.sensor_data: Dict[str, HardwareComponent] = {}
        self.update_interval = 1.0  # 秒
        self.running = False
        
    async def initialize(self) -> bool:
        """初始化硬件监控"""
        try:
            # 尝试加载LibreHardwareMonitor
            import LibreHardwareMonitor.Hardware
            self.hardware_monitor = LibreHardwareMonitor.Hardware.Computer()
            self.hardware_monitor.IsCpuEnabled = True
            self.hardware_monitor.IsGpuEnabled = True
            self.hardware_monitor.IsMemoryEnabled = True
            self.hardware_monitor.IsMotherboardEnabled = True
            self.hardware_monitor.IsControllerEnabled = True
            self.hardware_monitor.IsStorageEnabled = True
            self.hardware_monitor.IsNetworkEnabled = True
            self.hardware_monitor.Open()
            return True
            
        except ImportError:
            # 降级到psutil基础监控
            print("LibreHardwareMonitor不可用，使用psutil基础监控")
            import psutil
            self.fallback_monitor = psutil
            return True
            
        except Exception as e:
            print(f"硬件监控初始化失败: {e}")
            return False
    
    async def start_monitoring(self) -> None:
        """开始监控"""
        if self.running:
            return
        
        self.running = True
        
        while self.running:
            try:
                await self.update_sensor_data()
                await asyncio.sleep(self.update_interval)
            except Exception as e:
                print(f"监控更新失败: {e}")
                await asyncio.sleep(5)  # 出错后等待5秒再重试
    
    async def stop_monitoring(self) -> None:
        """停止监控"""
        self.running = False
    
    async def update_sensor_data(self) -> None:
        """更新传感器数据"""
        if self.hardware_monitor:
            await self._update_libre_hardware_data()
        elif self.fallback_monitor:
            await self._update_psutil_data()
    
    async def _update_libre_hardware_data(self) -> None:
        """更新LibreHardwareMonitor数据"""
        self.hardware_monitor.Update()
        
        for hardware in self.hardware_monitor.Hardware:
            component = HardwareComponent(
                name=hardware.Name,
                component_type=self._get_component_type(hardware.HardwareType),
                sensors=[]
            )
            
            for sensor in hardware.Sensors:
                if sensor.Value is not None:
                    sensor_data = HardwareSensor(
                        name=sensor.Name,
                        value=float(sensor.Value),
                        unit=sensor.SensorType.ToString(),
                        min_value=float(sensor.Min) if sensor.Min else None,
                        max_value=float(sensor.Max) if sensor.Max else None,
                    )
                    component.sensors.append(sensor_data)
            
            self.sensor_data[hardware.Identifier] = component
    
    async def _update_psutil_data(self) -> None:
        """更新psutil数据"""
        import psutil
        
        # CPU监控
        cpu_component = HardwareComponent(
            name="CPU",
            component_type="cpu",
            sensors=[
                HardwareSensor("使用率", psutil.cpu_percent(interval=1), "%", 0, 100),
                HardwareSensor("核心数", psutil.cpu_count(logical=False), "个"),
                HardwareSensor("逻辑核心数", psutil.cpu_count(logical=True), "个"),
            ]
        )
        self.sensor_data["cpu"] = cpu_component
        
        # 内存监控
        memory = psutil.virtual_memory()
        memory_component = HardwareComponent(
            name="内存",
            component_type="memory",
            sensors=[
                HardwareSensor("使用率", memory.percent, "%", 0, 100),
                HardwareSensor("已使用", memory.used / 1024**3, "GB"),
                HardwareSensor("可用", memory.available / 1024**3, "GB"),
                HardwareSensor("总量", memory.total / 1024**3, "GB"),
            ]
        )
        self.sensor_data["memory"] = memory_component
        
        # 磁盘监控
        disk = psutil.disk_usage('/')
        disk_component = HardwareComponent(
            name="磁盘",
            component_type="storage",
            sensors=[
                HardwareSensor("使用率", disk.percent, "%", 0, 100),
                HardwareSensor("已使用", disk.used / 1024**3, "GB"),
                HardwareSensor("可用", disk.free / 1024**3, "GB"),
                HardwareSensor("总量", disk.total / 1024**3, "GB"),
            ]
        )
        self.sensor_data["disk"] = disk_component
        
        # 网络监控
        net_io = psutil.net_io_counters()
        network_component = HardwareComponent(
            name="网络",
            component_type="network",
            sensors=[
                HardwareSensor("发送字节", net_io.bytes_sent, "bytes"),
                HardwareSensor("接收字节", net_io.bytes_recv, "bytes"),
            ]
        )
        self.sensor_data["network"] = network_component
        
        # GPU监控 (需要额外库支持)
        try:
            import GPUtil
            gpus = GPUtil.getGPUs()
            for i, gpu in enumerate(gpus):
                gpu_component = HardwareComponent(
                    name=f"GPU {gpu.name}",
                    component_type="gpu",
                    sensors=[
                        HardwareSensor("使用率", gpu.load * 100, "%", 0, 100),
                        HardwareSensor("温度", gpu.temperature, "°C", 0, 100),
                        HardwareSensor("显存使用", gpu.memoryUsed, "MB"),
                        HardwareSensor("显存总量", gpu.memoryTotal, "MB"),
                    ]
                )
                self.sensor_data[f"gpu_{i}"] = gpu_component
        except ImportError:
            pass
    
    def _get_component_type(self, hardware_type) -> str:
        """获取组件类型"""
        type_map = {
            "Cpu": "cpu",
            "GpuNvidia": "gpu",
            "GpuAmd": "gpu",
            "GpuIntel": "gpu",
            "Memory": "memory",
            "Storage": "storage",
            "Network": "network",
            "Motherboard": "motherboard",
        }
        return type_map.get(hardware_type.ToString(), "unknown")
    
    def get_sensor_data(self) -> Dict[str, HardwareComponent]:
        """获取传感器数据"""
        return self.sensor_data.copy()
    
    def get_component_data(self, component_type: str) -> List[HardwareComponent]:
        """获取指定类型的组件数据"""
        return [
            component for component in self.sensor_data.values()
            if component.component_type == component_type
        ]
    
    def get_critical_alerts(self) -> List[Dict[str, Any]]:
        """获取关键警报"""
        alerts = []
        
        for component_id, component in self.sensor_data.items():
            for sensor in component.sensors:
                # 检查温度警报
                if sensor.unit == "°C" and sensor.value > 80:
                    alerts.append({
                        "component": component.name,
                        "sensor": sensor.name,
                        "value": sensor.value,
                        "message": f"{component.name} {sensor.name}温度过高: {sensor.value}°C",
                        "level": "critical"
                    })
                
                # 检查使用率警报
                elif sensor.unit == "%" and sensor.value > 90:
                    alerts.append({
                        "component": component.name,
                        "sensor": sensor.name,
                        "value": sensor.value,
                        "message": f"{component.name} {sensor.name}使用率过高: {sensor.value}%",
                        "level": "warning"
                    })
        
        return alerts